/*

	when use shadow -> very heavy, less element are autorized.
	@use
		new Fx.TweenSheet().tween(".test", "background-color", "#FACADE");
		new Fx.TweenSheet().tween(".test", "background-color", ["#FACADE", "#FFA722"]);
		new Fx.TweenSheet().tween(".test", "transform", [0, 360], {pattern: "rotate(@px)", prefix:true});
*/

Fx.TweenSheet = new Class({
	
	Extends: Fx.CSS,
	
	options: {
		forceRender : false,
		pattern: false,
		prefix: false
	},
	
	/* Implements FX.CSS */
	
	initialize: function(options){
		this.globalStyleElement = $("TweenSheet") || new Element("style", {"id": "TweenSheet"}).inject($(document).getElement('head'));
		this.globalSheet = this.getSheet("TweenSheet");
		this.prefix = this.getPrefix();
		this.styleElement = document.createElement("style");
		document.getElementsByTagName("head")[0].appendChild(this.styleElement);
		this.styleSheet = this.getSheet();
		
		this.parent(options);
		
		this.options.prefix = this.getPrefix(); 
	},
	
	set: function(property, now){
		if (arguments.length == 1){
			now = property;
			property = this.property || this.options.property;
		}
		this.render(this.element, property, now[0].value, this.options.unit);
		return this;
	},
	
	start: function(property, from, to){
		
		if (!this.check(property, from, to)) return this;
		var args = Array.flatten(arguments);
		this.property = this.options.property || args.shift();
		var parsed = this.prepare(this.element, this.property, args);
		this.datas.from = parsed.from[0].value;
		return this.parent(parsed.from, parsed.to);
	},
	
	render: function(selector, property, value, unit){
		this.datas.to = value;
		this.datas.unit = unit;
		this.write(this.styleSheet, this.datas);
	},
	
	onComplete: function (){
		this.write(this.globalSheet, this.datas);
		this.cleanDOM();
	},
	
	/* Extends FX.CSS */

	tween: function (selector, property, fromTo){
		// si plus de 1 "@" dans le pattern
 		if(this.options.pattern && this.options.pattern.split("@").length > 3) return this.complex(arguments);
		
		this.element = $$(selector)[0];
		this.datas = {selector:selector, property:property};
		this.start(property, fromTo); // will finally execute the render method above
	},
	
	tweens: function (selector, oRules){
		for(var r in oRules){
			if(oRules[r].push) new Fx.TweenSheet().tween(selector, r, oRules[r][0], oRules[r][1]);
			else new Fx.TweenSheet(this.options).tween(selector, r, oRules[r]);
		}
		this.cleanDOM();
	},
	
	complex: function (selector, property, from, to){
		new Log("TweenSheetComplex is in progress, really no code is actually write, i keep this in mind, but if you got idea of what the script should do, just tell me, it could be interesting ! => ", selector, property, from, to);
		new Fx.TweenSheetComplex(this.options).tween();
		this.cleanDOM();
	},
	
	/* Utilities */
	
	write: function (sheet, oRule) {
		var isColor = /color/i.test(oRule.property);
		
		if(!oRule.unit && !isColor) oRule.unit = "px";
		else if (isColor || this.options.pattern) oRule.unit = "";
		
		if(isColor && oRule.to.push ){
			oRule.to = oRule.to.rgbToHex();
		}
		
		if(this.options.pattern) {
			var rule = this.options.pattern.replace(/@/, oRule.to) + ((this.options.forceRender) ? '!important;' : '');
		}
		else {
			var rule = oRule.to + oRule.unit + ((this.options.forceRender) ? '!important;' : '');
		}
		
		this.insertRule(sheet, oRule.selector, oRule.property, rule);
		if(this.options.prefix){
			this.insertRule(sheet, oRule.selector, this.options.prefix + oRule.property, rule);
		}
		
	},
	
	insertRule: function (sheet, selector, property, rule) {
		console.log(selector, property, rule)
		if (sheet.insertRule) {  
			sheet.insertRule(selector + '{' + property + ":" + rule + '}', sheet.cssRules.length);  
		}  
		else { /* IE */  
			sheet.addRule(selector, property + ":" + rule, -1);  
		}  
	},
	
	getSheet: function(id){
		var sss = document.styleSheets, l = sss.length - 1;
		if(sss[0].insertRule){
			for(var i=l;i>=0;i--){
				if(id && sss[i].ownerNode.id == id) return sss[i];
				else if(sss[i].ownerNode == this.styleElement) return sss[i];
			}
		} else {
			for(var i=l;i>=0;i--){
				if(id && sss[i].id == id) return sss[i];
			}
			return sss[l]
		}
		return false;
	},
	
	getPrefix: function (){
		switch(true){
			case Browser.Engine.gecko: return "-moz-";
			case Browser.Engine.webkit: return "-webkit-";
			case Browser.Engine.presto: return "-o-";
			case Browser.Engine.trident: return "-ms-";
		}
		return "";
	},
	
	cleanDOM: function (){
		// supp <style>
		this.styleElement.dispose();
		
		// clean globalStyle
		var rulesDump = {};	
		
		function rulePush(selectorText, cssText){
			if(!rulesDump[selectorText]) rulesDump[selectorText] = {};
			oSelector = rulesDump[rule.selectorText];
			cssText = cssText.substring(cssText.indexOf("{") + 1, cssText.indexOf("}"))//.replace(/ /g, "");
			var rules = cssText.split(";");
			if(rules.getLast().replace(/ /g, "") == "") rules.pop();
			rules.each(function (rule){	
				var kv = rule.split(":");
				rulesDump[selectorText][kv[0]] = kv[1].trim();
				
			});
		}
		
		
		// dump stylesheet while cleaning it
		if(this.globalSheet.insertRule){
			var rules = this.globalSheet.cssRules;
			var rule = rules[0];
			while(rules[0]){
				rulePush(rule.selectorText, rule.cssText);
				this.globalSheet.deleteRule(0);
				rule = rules[0];
			}
		} else {
			for(var i=l;i>=0;i--){
				if(id && sss[i].id == id) return sss[i];
			}
			return sss[l]
		}
		// rewrite stylesheet
		for(var sel in rulesDump){
			var rule = "";
			for(var property in rulesDump[sel]){
				rule += property + ":" + rulesDump[sel][property] + ";";
			}
			if (this.globalSheet.insertRule) {
				this.globalSheet.insertRule(sel + '{' + rule + '}', this.globalSheet.cssRules.length);  
			}  
			else { /* IE */  
				this.globalSheet.addRule(oRule.selector, rule, -1);  
			}
		}
	}
});

// background: rotate(@deg)

// -moz 
// -webkit
/*
var data = [1, 1, 1, "#ffO"];
var pattern = "@px @px @px @";

var result = pattern.replace(/@/g, function (){
    return data.shift()
})

{
	property: "box-shadow",
	pattern: "@px @px @px @"
} 
console.log(result)
*/


Fx.TweenSheetComplex = new Class({
	// {
		// property: "box-shadow",
		// pattern: "@px @px @px @"
	// }
});